/**
 * @brief HTTP模块,支持GET POST两种操作。如果需要考虑HTTPS 那么这个模块同样可以实现
 * @version 1.0
 * @date 2018-3-20
 * @author 宋炜
 */
#ifndef HTTP_HPP
#define HTTP_HPP
#include <string>

#include <curl/curl.h>
#include "filterio.h"

class filterList;

class http : public filterIO
{
public:
   	 enum mtd{ GET , POST };
private:
	std::string         m_server;           // 服务器
	std::string         m_url;              // URL
	std::string         m_head;             // 头信息
	std::string         m_cert;             // 客户端数字证书路径
	std::string         m_caPath;           // 用来验证服务器的CA
	mtd                 m_mtd;              // 数据提交方法

	int                 m_port;             // 连接端口
	std::atomic<bool>   m_sdp_en;           // 是否开启SDP
	bool                m_https;	    	// https
	bool                m_keepalive;        // http keepalive

	int                 m_respond_overtime; // 操作超时时间

	CURL                * ptctx;		// 使用CURL 作为HTTP后台操作的协议层引擎。
	struct curl_slist   * ptHeaders;        // HTTP头信息结构

public:
	/**
	 * @brief 构造http客户端
	 * @param l
	 */
	http( filterList * l );
	virtual ~http();
	/**
	 * @brief 设置服务器地址，这个地址可以是域名也可以是IP地址
	 * @param svr , 服务器地址
	 * @param port , 服务器监听端口
	 */
	http& server( const std::string& svr  );
	const std::string server( int &port )const;
	http& server( const std::string& svr , int port );
	/**
	 * @brief 设置URL，注意这个URL必须是经过URL格式化的数据。
	 * @note 千万注意不要传递没有经过URL格式化的数据
	 */
	http& url   ( const std::string& url  );
	const std::string url( ) const;
	/**
	 * @brief 设置头信息。
	 *
	 */
	http& head  ( const std::string& head );
	const std::string head( ) const;
	/**
	 * @brief
	 */
	http& cert  ( const std::string& cert );
	const std::string cert()const;
	/**
	 * @brief 开启则使用Https协议
	 * @param ssl
	 * @return
	 */
	http& ssl( bool ssl );
	bool ssl()const;
	/**
	 */
	http& port( int port );
	int port()const;
	/**
	 */
	http& keepalive( bool keep );
	bool keepalive()const;
private:
	/**
	 */
	bool on_forward( size_t len , const char * date , err_code &err , size_t& rlen , char ** rd );
	bool on_backward( size_t len , const char * data , err_code &err , size_t& rlen , char ** rd  );
	/**
	 */
	int do_post( const char * data );
	int do_post( const std::string& data );
	/**
	 */
	int do_get( const char* data );
	int do_get( const std::string& data );
	/**
	 * @brief 初始化HTTP头信息
	 */
	int init_headers();
	/**
	 * @brief 构造HTTP 头结构体
	 */
	void init_header_struct();
	/**
	 * @brief 分析字符串，找出换行符号的位置。
	 * @param str, 要分析的字符串
	 * @param line_width ， 换行符号的宽度。
	 * @note 换行符号在不同的操作系统下会有不同的定义，在windows下为\r\n， 其宽度为2
	 *       在*unix下通常为\n，宽度为1.
	 * @return 返回换行符号的的位置。如果是回车换行符号则返回回车符号的位置
	*/
	size_t find_line_pos( const std::string& str , size_t &line_width );
};

#endif // HTTP_HPP
